package service

import (
	"context"
	"fmt"
	"intelli-dl-online-logo-go/repository"
	"intelli-dl-online-logo-go/utils"
	"math/rand"
	"time"
)

type VerifyService interface {
	SendSMSCode(phone string) error
	SendEmailCode(email string) error
	VerifySMSCode(phone, code string) (bool, error)
	VerifyEmailCode(email, code string) (bool, error)
}

type verifyServiceImpl struct {
	verifyRepo repository.VerifyRepository
	userRepo   repository.UserRepository
}

func NewVerifyService(verifyRepo repository.VerifyRepository, userRepo repository.UserRepository) VerifyService {
	return &verifyServiceImpl{verifyRepo: verifyRepo, userRepo: userRepo}
}

func (vs *verifyServiceImpl) SendSMSCode(phone string) error {
	code := generateRandomCode()
	return vs.verifyRepo.StoreSMSCode(context.Background(), phone, code)
}

func (vs *verifyServiceImpl) SendEmailCode(email string) error {
	// 检查邮箱是否已注册
	ctx := context.Background()

	// 需要添加FindByEmail方法，这里先通过查询所有用户来检查
	user, err := vs.userRepo.FindByEmail(ctx, email)
	if err == nil && user != nil {
		return fmt.Errorf("该邮箱已注册，请直接登录")
	}

	// 检查是否已经发送过验证码
	existingCode, err := vs.verifyRepo.GetEmailCode(ctx, email)
	if err == nil && existingCode != "" {
		return fmt.Errorf("验证码已发送，请查收邮件，5分钟内有效")
	}

	// 生成验证码
	code := generateRandomCode()

	// 发送邮件
	mailSender, err := utils.NewMailSender()
	if err != nil {
		return fmt.Errorf("邮件服务初始化失败: %v", err)
	}

	// 加载邮件模板
	err = mailSender.LoadTemplate("templates/email_verification.html")
	if err != nil {
		return fmt.Errorf("加载邮件模板失败: %v", err)
	}

	// 准备邮件数据
	mailData := map[string]interface{}{
		"Code":          code,
		"ExpireMinutes": utils.EMAIL_CODE_EXPIRE / 60,
	}

	// 发送邮件
	err = mailSender.SendMail([]string{email}, mailData)
	if err != nil {
		return fmt.Errorf("发送邮件失败: %v", err)
	}

	// 存储验证码到Redis
	return vs.verifyRepo.StoreEmailCode(ctx, email, code)
}

func (vs *verifyServiceImpl) VerifySMSCode(phone, code string) (bool, error) {
	storedCode, err := vs.verifyRepo.GetSMSCode(context.Background(), phone)
	if err != nil {
		return false, err
	}
	return storedCode == code, nil
}

func (vs *verifyServiceImpl) VerifyEmailCode(email, code string) (bool, error) {
	storedCode, err := vs.verifyRepo.GetEmailCode(context.Background(), email)
	if err != nil {
		return false, err
	}
	return storedCode == code, nil
}

func generateRandomCode() string {
	rand.Seed(time.Now().UnixNano())
	return fmt.Sprintf("%06d", rand.Intn(1000000))
}
